package main

/**
	指针
	1、理解：常见定义的变量是编程语言中方便开发者编写和理解代码的一个标签。如：var name string = "zhouhailin"
    	    访问这个标签的时候，计算机会返回它指向的内存地址里存储的值。
			出于某些需要，会将这个内存地址赋值给另一个变量名，通常称为 pointer，这个变量称为指针变量。

	2、其实，指针变量的值就是内存地址
		-》 普通变量：存数据值本身   （结果）
		-》 指针变量：存值的内存地址	（目的地）

	3、& 和 * 符号的用法
		& ：从一个普通变量中取得内存地址
		* ：当*在赋值操作符（=）的右边，是从一个指针变量中取得变量值，当*在赋值操作符（=）的左边，是指该指针指向的变量

*/
import "fmt"

func main() {

	/**
	创建指针的3种方法
	*/
	// 第1种
	// 普通变量
	aint := 1
	// 定义指针变量
	ptr := &aint
	fmt.Println(aint)
	fmt.Println(ptr)
	fmt.Println("================================================")

	// 第2种 (先创建指针，分配好内存后，再给指针指向的内存地址写入对应的值)
	// 创建指针
	astr := new(string)
	// 给指针赋值
	*astr = "zhouhailin"
	fmt.Println(astr)
	fmt.Println("================================================")

	// 第3种 （先声明一个指针变量，再从其他变量取得内存地址赋值给它）
	point_A := 1
	// 声明一个指针
	var point_B *int
	point_B = &point_A
	fmt.Println(point_B)
	fmt.Println("================================================")

	point_A1 := 100
	point_A2 := &point_A1
	fmt.Println("普通变量存储的是：", point_A1)
	fmt.Println("普通变量存储的是：", *point_A2)
	fmt.Println("指针变量存储的是：", &point_A1)
	fmt.Println("指针变量存储的是：", point_A2)
	fmt.Println("================================================")

	/**
	指针类型
	*/
	astr1 := "hello"
	aint1 := 1
	abool1 := false
	arune1 := 'a'
	afloat1 := 1.2

	fmt.Printf("astr 指针类型是：%T\n", &astr1)
	fmt.Printf("aint 指针类型是：%T\n", &aint1)
	fmt.Printf("abool 指针类型是：%T\n", &abool1)
	fmt.Printf("arune 指针类型是：%T\n", &arune1)
	fmt.Printf("afloat 指针类型是：%T\n", &afloat1)
	fmt.Println("================================================")

	/**
	指针的零值
	*/
	a := 100
	var b *int
	if b == nil {
		fmt.Println(b)
		b = &a
		fmt.Println(b)
	}
	fmt.Println("================================================")

	/**
	指针与切片
	问题：通过一个函数改变一个数组的值，2种方法
		1、将这个数组的切片做为参数传给函数
		2、将这个数组的指针做为参数传给函数
	*/
	// 使用数组
	a1 := [3]int{89, 90, 91}
	modify_1(a1[:])
	fmt.Println(a1)

	// 使用切片
	a2 := [3]int{101, 102, 103}
	modify_2(&a2)
	fmt.Println(a2)
}

// 使用切片
func modify_1(sls []int) {
	sls[0] = 90
}

// 使用指针
func modify_2(arr *[3]int) {
	(*arr)[0] = 90
}
